package com.cloud.quickconfigure.rabbitmq;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.utils.SerializationUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;

/**
 * RabbitMq配置
 */
@Configuration
@Slf4j
@EnableRabbit
public class RabbitMQConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {


    @Bean
    public ConnectionFactory connectionFactory(RabbitProperties properties) {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(properties.getHost(), properties.getPort());
        connectionFactory.setUsername(properties.getLogin());
        connectionFactory.setPassword(properties.getPassword());
        connectionFactory.setVirtualHost(properties.getVhost());
        connectionFactory.setPublisherConfirms(properties.isConfirm());
        connectionFactory.setPublisherReturns(properties.isReturns());
        return connectionFactory;
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setConfirmCallback(this);
        template.setReturnCallback(this);
        return template;
    }

    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
        return new RabbitAdmin(connectionFactory);
    }

    /**
     * 消息达到交换机回调
     */
    @Override
    public void confirm(@Nullable CorrelationData correlationData, boolean ack, @Nullable String cause) {
        log.info("消息唯一标识:{},确认结果:{},失败原因:{}", correlationData, ack, cause);
    }

    /**
     * 交换机到达队列回调
     */
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingkey) {
        log.info("消息主体:{},消息状态码:{},描述:{},使用交换机:{},路由规则:{}", SerializationUtils.deserialize(message.getBody()), replyCode, replyText, exchange, routingkey);
    }
}
